home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Floppyshop 2
/
Floppyshop - 2.zip
/
Floppyshop - 2.iso
/
art&graf.ix
/
art-3871
/
mdl10
/
flicker.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-06
|
24KB
|
1,132 lines
/*
* flicker.c - display grayscale image with flicker mode
*
* modified for dl/gl files. pimg points to all the raw images and
* nframes is the number of frames. no histogram stuff at all. handles
* dl commands (which is a list of frame indices in order).
*
* note: I16 is 16 bit integer so we don't care what an "int" is
* external to this routine. when u see 96000, it is really
* 48000 * sizeof(I16). most things here are actually tuned to 16 bit
* ints.
*
* now ansi for gcc. -mshort not needed.
*
* compilation control:
* NEW_RANDOM def to use new random noise code
* NO_INVERT def to invert pixel intensities (normally
* undefined)
*/
typedef short I16;
typedef unsigned short UI16;
#ifndef lint
static char *rcsid = "$Id: flicker.c,v 1.3 1991/07/24 17:13:48 rosenkra Exp $";
#endif
/*
* $Log: flicker.c,v $
* Revision 1.3 1991/07/24 17:13:48 rosenkra
* now RCS. fix flicker for SimpConv2Gray so image is not so dark. also
* make sure last work in each pixel row gets dumped to screen when
* using SimpConv2Gray (e.g. during cut or zoom).
*
* Revision 1.2 1991/07/16 23:24:48 rosenkra
* released june 91 to usenet. first RCS revision.
*
*/
/*
* this is for screen-switching on mono to simulate grayscale. it
* uses a combination of floyd-steinberg and simulate "planes" which
* get displayed each vblank. the image it works from should be
* grayscale, i.e. each pixel is represented by an 8-bit (0 to 255)
* intensity. since GIF images come with a color table, it is first
* required to map each GIF pixel to the color table which has been
* first changed to grayscale, either by averaging the rgb values
* or by using the NTSC intensity equation.
*
* note that i think the f-s algorithm employed here sweeps each row
* left to right rather than alternating directions. that is why there
* is spurious info in areas otherwise supposed to be white.
*
* also, all points where chars are used in a calculation, they MUST
* be unsigned.
*
* return ptr to screens.
*/
/* written by Klaus Pedersen (micro@imada.dk) */
/* modified by Bill Rosenkranz (rosenkra@convex.com) */
#include <stdio.h>
#include <types.h>
#include <stdlib.h> /* for malloc */
#include <string.h> /* for bzero */
#include <osbind.h>
#define LEVELS 4
#define NUMERRS 1024
#define SCRNSPACE 48256L /* now per frame */
#define MAXFRAMES 25 /* 25 needs 2.4 MB (96000B/frame) */
/*
* globals.
*
* these are the thresholds for quantizing. 0,85,170,255 seem best
*/
static I16 _Levels[LEVELS] = { 0, 85, 170, 255};
static I16 _SimpLevels[LEVELS] = { 0, 255};
static int _Show; /* print progress to stdout if !=0 */
static int _Delay; /* ms delay between frames (if +ve) */
static I16 _Nframes; /* number of frames in raster */
static I16 _Ncommands; /* number of commands */
static I16 _Width; /* image size */
static I16 _Hight;
static I16 _Beta; /* for the Laplace filter */
static I16 _MaxRandom; /* for adding random noise */
static I16 *_Err1, /* the error propagation arrays */
*_Err2;
static I16 _Err1Array[NUMERRS],
_Err2Array[NUMERRS];
static I16 *_Scrn, /* we malloc space here */
*_Scrn1[MAXFRAMES],
*_Scrn2[MAXFRAMES],
*_Scrn3[MAXFRAMES];
/*
* local functions
*/
static void _Conv2Gray (unsigned char *, int *);
static void _SimpConv2Gray (unsigned char *, int *);
static I16 _GenConvPix (unsigned char *, int, int);
static I16 _SimpGenConvPix (unsigned char *, int, int);
static I16 _Laplace (unsigned char *);
static void _ClearErr (void);
static I16 _Rand (I16);
/*------------------------------*/
/* dl_flicker */
/*------------------------------*/
int dl_flicker (unsigned char *pimg, int nframes, int width, int hight,
int beta, int maxrandom, int opt, int delay, int *cmd,
int ncommands, int show)
/* pimg -> raster image sequence (intensities) */
/* nframes number of frames in pimg */
/* width width, pixels */
/* hight height, pixels */
/* beta for laplace filter */
/* maxrandom for random noise */
/* opt 0=no flicker, 1=flicker */
/* delay ms delay between images */
/* cmd -> commands (order to display frames) */
/* ncommands number of commands (total frames in loop) */
/* show print info to stdout if != 0 */
{
/*
* this is the main entry point. complete grayscale raster image
* comes from pimg with height and width specified. if beta != 0,
* do Laplace filter with that beta. if maxrandom != 0, add some
* random noise with that value (see below).
*
* pimg contains each basic frame in succession.
*
* dl commands are used. do this in loop showing the basic screens
* by indexing into _Scrn* as _Scrn*[cmd[i]].
*
* return 0 if ok. 1 if error.
*/
/*
* set our globals
*/
_Show = show;
_Nframes = (I16) nframes; /* number of frames in raster */
_Ncommands = (I16) ncommands; /* number of commands in animation */
_Delay = delay; /* ms delay between frames */
_Hight = (I16) hight; /* its height... */
_Width = (I16) width; /* ...and width */
_Beta = (I16) beta; /* Laplace filter coefficient */
/* 1=0.25, 2=0.50, 3=0.75... (Try 4) */
_MaxRandom = (I16) maxrandom; /* amount of random noise, 0-255 */
/* for 0% to 100% noise. (Try 10) */
/*
* check nframes.
*/
if (_Show)
printf ("flicker: num frames = %d, max allowed = %d\n",
_Nframes, MAXFRAMES);
if (_Nframes > MAXFRAMES)
_Nframes = MAXFRAMES;
/*
* allocate space for all screens. note that sizeof(I16) is 2.
*/
if (opt)
{
if (_Show)
printf ("flicker: allocating memory, flicker mode (%ld bytes)\n",
96000L * (long)_Nframes);
_Scrn = (I16 *) malloc (96000 * (size_t) _Nframes + 256);
}
else
{
if (_Show)
printf ("flicker: allocating memory, not flicker (%ld bytes)\n",
32000L * (long)_Nframes);
_Scrn = (I16 *) malloc (32000 * (size_t) _Nframes + 256);
}
if (_Scrn == (I16 *) NULL)
{
if (_Show)
printf ("flicker: memory allocation failed\n");
return (1);
}
/*
* make sure screen is aligned on 256-byte boundary.
*/
_Scrn = (I16 *) (((long) _Scrn + 256L) & 0xFFFFFF00L);
/*
* clear screens. this may not have to be done if malloc clears
* or if the dithering touches everything
*/
if (_Show)
printf ("flicker: clearing memory...\n");
if (opt)
bzero (_Scrn, (size_t) (96000 * _Nframes));
else
bzero (_Scrn, (size_t) (32000 * _Nframes));
/*
* do it!
*/
if (opt)
_Conv2Gray (pimg, cmd);
else
_SimpConv2Gray (pimg, cmd);
return (0);
}
/*------------------------------*/
/* _Conv2Gray */
/*------------------------------*/
static void _Conv2Gray (unsigned char *pic, int *cmd)
{
unsigned char *ppic;
register int i;
int j;
register I16 x;
I16 y;
I16 w;
I16 h;
register long yoffset;
I16 *TmpErr;
register I16 q;
I16 rover1;
I16 rover2;
register UI16 pix;
unsigned char *p;
char *old1;
char *old2;
int rpt;
int done;
/*
* number of times to repeat inner display loop showing a single
* frame. this is to deal with different frame rates. 40 ms for
* three Setscreen/Vsync is about right on 8MHz ST...
*/
rpt = _Delay / 40;
/*
* save old screen info
*/
old1 = (char *) Logbase ();
old2 = (char *) Physbase ();
/*
* clear...
*/
if (_Show)
printf ("flicker: clear screen...\n");
bzero (old1, (size_t) 32000);
bzero (old2, (size_t) 32000);
/*
* we will set physbase to our buffer and _Scrn1[0] points to it.
* set the other screen pointers. _Scrn is a buffer large enuf
* to hold all 3 screens for every frame. it would obviously be
* more efficient to blit the images rather than store the entire
* screen if the image is smaller than the entire screen.
*/
_Scrn1[0] = _Scrn;
_Scrn2[0] = _Scrn1[0] + 16000L;
_Scrn3[0] = _Scrn2[0] + 16000L;
for (i = 1; i < _Nframes; i++)
{
_Scrn1[i] = _Scrn3[i-1] + 16000L;
_Scrn2[i] = _Scrn1[i] + 16000L;
_Scrn3[i] = _Scrn2[i] + 16000L;
}
/*
* we have to dither each frame so be patient...
*/
for (ppic = pic, i = 0; i < _Nframes; i++, ppic += _Hight*_Width)
{
/*
* monitor the progress of dithering.
* set logbase to old physbase and physbase to first
* screen buffer. we *should* never see logbase in the
* displayed image since we never display logbase.
*/
Setscreen (old2, (long) _Scrn1[i], -1); Vsync ();
/*
* first clear the error arrays
*/
_ClearErr ();
/*
* initialize some things. yoffset positions us into each
* screen which are int arrays. each scan line in the
* screen is thus 40 words long.
*/
yoffset = 0L;
rover1 = 0;
rover2 = 0;
/*
* loop over all rows in image
*/
h = (_Hight > 400) ? 400 : _Hight;
for (y = 1; y < h - 1; y++)
{
/*
* set ptr to this pixel row
*/
p = ppic + ((long) y * (long) _Width);
/*
* loop over all pixels in the row
*/
w = (_Width > 640) ? 640 : _Width;
for (x = 0; x < w - 1; x++)
{
pix = (0x8000 >> (x & 0x000f));
/*
* get new pixel value, with f-s error.
* this is actually an index into the
* _Levels array.
*/
if (y & 1)
q = _GenConvPix (p, (int) x, 0);
else
q = _GenConvPix (p, (int) x, 1);
/*
* set screen pixels based on this index
*/
if (q == 1)
{
switch (rover1)
{
case 0:
_Scrn1[i][yoffset + (x >> 4)] |= pix;
rover1 = 1;
rover2 = 1;
break;
case 1:
_Scrn2[i][yoffset + (x >> 4)] |= pix;
rover1 = 2;
rover2 = 2;
break;
case 2:
_Scrn3[i][yoffset + (x >> 4)] |= pix;
rover1 = 0;
rover2 = 0;
break;
}
}
else if (q == 2)
{
switch (rover2)
{
case 0:
_Scrn1[i][yoffset + (x >> 4)] |= pix;
_Scrn2[i][yoffset + (x >> 4)] |= pix;
rover2 = 1;
rover1 = 2;
break;
case 1:
_Scrn2[i][yoffset + (x >> 4)] |= pix;
_Scrn3[i][yoffset + (x >> 4)] |= pix;
rover2 = 2;
rover1 = 0;
break;
case 2:
_Scrn1[i][yoffset + (x >> 4)] |= pix;
_Scrn3[i][yoffset + (x >> 4)] |= pix;
rover2 = 0;
rover1 = 1;
break;
}
}
else if (q == 3)
{
_Scrn1[i][yoffset + (x >> 4)] |= pix;
_Scrn2[i][yoffset + (x >> 4)] |= pix;
_Scrn3[i][yoffset + (x >> 4)] |= pix;
}
}
/*
* get ready for next row by incrementing offset
* into the screens (640 dots = 40 words)
*/
yoffset += 40;
/*
* exchange error arrays
*/
TmpErr = _Err1;
_Err1 = _Err2;
_Err2 = TmpErr;
/*
* check for early withdrawal...
*/
if (Bconstat (2))
{
while (Bconstat (2))
(void) Bconin (2);
Setscreen ((long) old1, (long) old2, -1);
return;
}
}
}
/*
* now set screen to first image...
*/
Setscreen (old2, (long) _Scrn, -1); Vsync ();
/*
* with that all done, now we can display the screens. only
* phys screen is displayed (at next vblank). the Vsync waits
* for the vblank. we display screens 1,2,3. any char stops the
* loop.
*
* it goes like this ("screen" is the dithered flicker screen):
*
* frame cmd[0] screen 1
* screen 2
* screen 3
* frame cmd[1] screen 1
* screen 2
* screen 3
* ...
*
* show screens at speed. wait for keypress (which ends the loop)...
*/
done = 0;
do
{
/*
* loop over commands. each cmd is a frame number.
*/
for (i = 0; i < _Ncommands; i++)
{
/*
* best way to do the delay seems to be display the
* same frame in a loop then move to the next. the
* trick is to find how long Setscreen/Vsync takes.
*/
for (j = 0; j < rpt; j++)
{
Setscreen (old2, _Scrn1[cmd[i]], -1); Vsync ();
Setscreen (old2, _Scrn2[cmd[i]], -1); Vsync ();
Setscreen (old2, _Scrn3[cmd[i]], -1); Vsync ();
}
if (Bconstat (2))
{
done = 1;
break;
}
}
} while (!done);
/*
* reset screens back to what they were
*/
Setscreen ((long) old1, (long) old2, -1);
/*
* clear any waiting keys...
*/
while (Bconstat (2))
(void) Bconin (2);
}
/*------------------------------*/
/* _SimpConv2Gray */
/*------------------------------*/
static void _SimpConv2Gray (unsigned char *pic, int *cmd)
{
/*
* I have also made a version of "Convert2Gray", that don't use
* flicker - this allows the pictures to be saved, and used in windows,
* and honest - the build-in test-picture looks as good, or even better,
* without the flicker... (this is not true for any *real* pictures
* that I have tested the program with). Here it is :
*/
unsigned char *ppic;
int i;
int j;
long x,
y,
yoffset,
wordpos;
I16 w,
h;
I16 *TmpErr;
UI16 pix;
unsigned char *p;
char *old1;
char *old2;
int rpt;
int done;
/*
* 15 ms for one Setscreen/Vsync is about right on 8MHz
* ST...
*/
rpt = _Delay / 15;
/*
* save old screen info
*/
old1 = (char *) Logbase ();
old2 = (char *) Physbase ();
/*
* clear...
*/
if (_Show)
printf ("flicker: clear screen...\n");
bzero (old1, (size_t) 32000);
bzero (old2, (size_t) 32000);
/*
* there is only one screen. we use existing physbase
*/
_Scrn1[0] = _Scrn;
for (i = 1; i < _Nframes; i++)
{
_Scrn1[i] = _Scrn1[i-1] + 16000L;
}
/*
* we have to dither each frame so be patient...
*/
for (ppic = pic, i = 0; i < _Nframes; i++, ppic += _Hight*_Width)
{
/*
* monitor the progress of dithering.
* set logbase to old physbase and physbase to first
* screen buffer. we *should* never see logbase in the
* displayed image since we never display logbase.
*/
Setscreen (old2, (long) _Scrn1[i], -1); Vsync ();
/*
* first clear the error arrays
*/
_ClearErr ();
/*
* yoffset positions us into the screen which is an int
* arrays.each scan line in the screen is thus 40 words
* long.
*/
yoffset = 0;
pix = 0;
/*
* loop over all rows in image
*/
h = (_Hight > 400) ? 400 : _Hight;
for (y = 1; y < h - 1; y++)
{
/*
* set ptr to this pixel row
*/
p = ppic + ((long) y * (long) _Width);
wordpos = yoffset;
/*
* loop over all pixels in the row
*/
w = (_Width > 640) ? 640 : _Width;
for (x = 0L; x < w; x++)
{
pix <<= 1;
if (_SimpGenConvPix (p, (int) x, 0))
pix++;
if ((x & 0x0f) == 0x0f)
_Scrn1[i][wordpos++] = pix;
}
/*
* clean up last word if any
*/
if (w % 16)
{
int shft;
shft = 16 - (w % 16);
pix <<= shft;
_Scrn1[i][wordpos++] = pix;
}
/*
* get ready for next row by incrementing offset
* into the screens (640 dots = 40 words)
*/
yoffset += 40;
/*
* exchange error arrays
*/
TmpErr = _Err1;
_Err1 = _Err2;
_Err2 = TmpErr;
/*
* check for early withdrawal...
*/
if (Bconstat (2))
{
while (Bconstat (2))
(void) Bconin (2);
Setscreen ((long) old1, (long) old2, -1);
return;
}
}
}
/*
* now set screen to first image...
*/
Setscreen (old2, (long) _Scrn, -1); Vsync ();
/*
* do it...
*/
done = 0;
do
{
/*
* loop over commands. each cmd is a frame number.
*/
for (i = 0; i < _Ncommands; i++)
{
/*
* the best way to do the delay seems to display the
* same frame in a loop then move to the next. the
* trick is to find how long a Setscreen/Vsync
* takes.
*/
for (j = 0; j < rpt; j++)
{
Setscreen (old2, _Scrn1[cmd[i]], -1); Vsync ();
}
if (Bconstat (2))
{
done = 1;
break;
}
}
} while (!done);
/*
* reset screens back to what they were
*/
Setscreen ((long) old1, (long) old2, -1);
/*
* clear any waiting keys...
*/
while (Bconstat (2))
(void) Bconin (2);
}
/*------------------------------*/
/* _GenConvPix */
/*------------------------------*/
static I16 _GenConvPix (unsigned char *pic, int x, int opt)
/* pic -> image pixel array */
/* x the current pixel */
/* opt 0=l to r, 1=r to l */
{
/*
* This routine converts a point in the 'real' image to
* a point in the screen image. The procedure uses error-
* diffusion to determine the state of the new pixel.
* The Error filter is that of Floyd & Steinberg :
*
* / 1 5 3 \ /
* \ 7 X / / 16
*
* This rutine uses a table of levels to make the convertion.
*
* It returns the index for the pixel from the quantizing Level
* array, i.e. the new pixel intensity is Level[i].
*/
register I16 *p_levels;
register I16 p;
register I16 e;
register I16 i;
register I16 err;
I16 lev = 0;
p_levels = _Levels;
#ifdef NEW_RANDOM
/*
The noise is here added to the picture, this means that the noise
isn't cancled out again, and that is NOT intended, the noise should
only act as some kind of *catalysator* (verb. is stolen from
chemistry - something that start a reaction).
*/
/*
* first do the weighted average. _Err1 is the current line,
* _Err2 is the previous line.
*/
if (x == 0)
{
# ifdef NO_INVERT
/*!!! next line was actually: */
p = *pic;
/*!!! but that inverted the image. it was assumed that 0xff
was black. we insist that black is 0x00 (low intensity)*/
# else /*!NO_INVERT*/
p = 255 - *pic;
# endif /*NO_INVERT*/
}
else if (_Beta)
{
p = ((7*_Err1[x - 1]
+ _Err2[x - 1] + 5*_Err2[x] + 3*_Err2[x + 1]) >> 4)
+ _Laplace (pic + x);
}
else
{
p = ((7*_Err1[x - 1]
+ _Err2[x - 1] + 5*_Err2[x] + 3*_Err2[x + 1]) >> 4)
# ifdef NO_INVERT
+ *(pic + x);
# else /*!NO_INVERT*/
+ (255 - *(pic + x));
# endif /*NO_INVERT*/
}
/*
* now calculate the residual errors
*/
err = NUMERRS;
for (i = 0; i < LEVELS; i++)
{
if (_MaxRandom)
e = p + _Rand (_MaxRandom) - p_levels[i];
else
e = p - p_levels[i];
if (e < 0)
e = -e;
if (e < err)
{
err = e;
lev = (I16) i;
}
}
_Err1[x] = p - p_levels[lev];
#else /*!NEW_RANDOM*/
if (x == 0)
{
# ifdef NO_INVERT
p = *pic;
# else /*!NO_INVERT*/
p = 255 - *pic;
# endif /*NO_INVERT*/
}
else if (_Beta)
{
if (_MaxRandom)
p = ((7 * _Err1[x - 1] + _Err2[x - 1]
+ 5 * _Err2[x] + 3 * _Err2[x + 1]) >> 4)
+ _Laplace (pic + x) + _Rand (_MaxRandom);
else
p = ((7 * _Err1[x - 1] + _Err2[x - 1]
+ 5 * _Err2[x] + 3 * _Err2[x + 1]) >> 4)
+ _Laplace (pic + x);
}
else
{
if (_MaxRandom)
{
p = ((7 * _Err1[x - 1] + _Err2[x - 1]
+ 5 * _Err2[x] + 3 * _Err2[x + 1]) >> 4)
# ifdef NO_INVERT
+ *(pic + x) + _Rand (_MaxRandom);
# else /*!NO_INVERT*/
+ (255 - *(pic + x)) + _Rand (_MaxRandom);
# endif /*NO_INVERT*/
}
else
{
p = ((7 * _Err1[x - 1] + _Err2[x - 1]
+ 5 * _Err2[x] + 3 * _Err2[x + 1]) >> 4)
# ifdef NO_INVERT
+ *(pic + x);
# else /*!NO_INVERT*/
+ (255 - *(pic + x));
# endif /*NO_INVERT*/
}
}
err = NUMERRS;
for (i = 0; i < LEVELS; i++)
{
e = p - p_levels[i];
if (e < 0)
e = -e;
if (e < err)
{
err = e;
lev = (I16) i;
}
}
_Err1[x] = p - p_levels[lev];
#endif /*NEW_RANDOM*/
return (lev);
}
/*------------------------------*/
/* _SimpGenConvPix */
/*------------------------------*/
static I16 _SimpGenConvPix (unsigned char *pic, int x, int opt)
/* pic -> image pixel array */
/* x the current pixel */
/* opt 0=l to r, 1=r to l */
{
/*
* This version is for SimpConv2Gray. no laplace, no noise...
*
* This rutine converts a point in the 'real' image to
* a point in the screen image. The procedure uses error-
* diffusion to determine the state of the new pixel.
* The Error filter is that of Floyd & Steinberg :
*
* / 1 5 3 \ /
* \ 7 X / / 16
*
* This rutine uses a table of levels to make the convertion.
*
* It returns the index for the pixel from the quantizing Level
* array, i.e. the new pixel intensity is Level[i].
*/
register I16 *p_levels;
register I16 p;
register I16 e;
register I16 i;
register I16 err;
I16 lev = 0;
p_levels = _SimpLevels;
/*
* first do the weighted average. _Err1 is the current line,
* _Err2 is the previous line.
*/
if (x == 0)
{
# ifdef NO_INVERT
/*!!! next line was actually: */
p = *pic;
/*!!! but that inverted the image. it was assumed that 0xff
was black. we insist that black is 0x00 (low intensity)*/
# else
p = 255 - *pic;
# endif
}
else
{
# ifdef NO_INVERT
p = ((7*_Err1[x - 1]
+ _Err2[x - 1] + 5*_Err2[x] + 3*_Err2[x + 1]) >> 4)
+ *(pic + x);
# else
p = ((7*_Err1[x - 1]
+ _Err2[x - 1] + 5*_Err2[x] + 3*_Err2[x + 1]) >> 4)
+ (255 - *(pic + x));
# endif
}
/*
* now calculate the residual errors
*/
err = NUMERRS;
for (i = 0; i < 2; i++)
{
e = p - p_levels[i];
if (e < 0)
e = -e;
if (e < err)
{
err = e;
lev = i;
}
}
_Err1[x] = p - p_levels[lev];
return (lev);
}
/*------------------------------*/
/* _Laplace */
/*------------------------------*/
static I16 _Laplace (unsigned char *Pic)
{
/*
* this is a Laplacian filter, a simple edge detector/enhancer.
*
* -1
* -1 4 -1
* -1
*/
register unsigned char *pc;
register I16 lp;
register I16 b;
register I16 w;
pc = Pic;
b = _Beta;
w = _Width;
/*
* if _Beta 0, formula reduces to just the pixel
*/
#ifdef NO_INVERT
if (b == 0)
return ((I16) *pc);
lp = (*pc << 2) /* this pixel */
- *(pc - 1) - *(pc + 1) /* left/right */
- *(pc + w) - *(pc - w); /* top/bottom */
lp = ((b * lp) >> 2) + *pc;
#else /*!NO_INVERT*/
if (b == 0)
return ((I16) (255 - *pc));
lp = (255 - *pc) << 2; /* this pixel */
lp -= (255 - *(pc - 1)); /* left/right */
lp -= (255 - *(pc + 1));
lp -= (255 - *(pc + w)); /* top/bottom */
lp -= (255 - *(pc - w));
lp = ((b * lp) >> 2);
lp += (255 - *pc); /* self */
#endif /*NO_INVERT*/
/*
* check limits and force result to 8 bits
*/
if (lp < 0)
lp = 0;
if (lp > 255)
lp = 255;
return (lp);
}
/*------------------------------*/
/* _ClearErr */
/*------------------------------*/
static void _ClearErr (void)
{
register int i;
register I16 w;
register I16 *pe1;
register I16 *pe2;
_Err1 = _Err1Array;
_Err2 = _Err2Array;
pe1 = _Err1Array;
pe2 = _Err2Array;
w = _Width;
for (i = 0; i < w; i++)
{
*pe1++ = 0;
*pe2++ = 0;
}
}
/*------------------------------*/
/* _Rand */
/*------------------------------*/
static I16 _Rand (I16 mx)
{
/*
* returns random number 0 <= x < mx. no real need to initialize this.
*/
static long Seed = 0;
if (mx == 0)
return (0);
Seed += (Seed << 2) + 37;
/* Seed &= 0x00007fffL;*/ /* should prevent overflow */
return (((I16) Seed) % mx);
}